#include "NullObjectPtr.h"
#include "TypeID.h"
#include "FunctionList.h"
#include "NativeFunction.h"
#include "TypeInstance.h"

class CNullObjectPtrInstance : public ITypeInstance
{
protected:
    CNullObjectPtr * Type;
public:
    CNullObjectPtrInstance(CNullObjectPtr * InType)
        :Type(InType)
    {
    }

    void InitInstance(void * InMemory) override
    {
        new (InMemory) TSharedObjectPtr<RObject>();
    }

    void EraseInstance(void * Instance) override
    {
        //do nothing
    }

    void CloneInstance(const void * Instance, void * Memory) override
    {
        //only one value for this type ,just new
        new (Memory) TSharedObjectPtr<RObject>();
    }   

    void *CreateInstance() override
    {
        return new TSharedObjectPtr<RObject>();
    }

    void ResetAllocated(void * InMemory) override
    {
        //do nothing,because this type only have one value
    }

    uint32_t GetSize() override
    {
        return sizeof(TSharedObjectPtr<RObject>);
    }

    CString ToDebugString(const void * InInstance) const override
    {
        return U"Null";
    }

    uint64_t GetInstanceHash(const void * InInstance) const override
    {
        return 0;
    }

    bool IsInstanceEqual(const void * A, const void * B) const override
    {
        return true;
    }

    bool IsForceConvertableTo(CType * Other) override
    {
        if(Other->IsSharedObjectPtrType())
        {
            return true;
        }

        return false;
    }

};


CNullObjectPtr::CNullObjectPtr()
    :CType(STypeID(U"NullObject",true)
    , ETypeFlags::ScriptInner )
{
    Instancable=new CNullObjectPtrInstance(this);
    Functions= new CFunctionList(this);
    {
        auto ToStringFunction = new CNativeFunction(
            Functions
            ,U"ToString"
            ,CGetType<CString>()()
            ,{}
            ,{}
            );
        ToStringFunction->SetCppBody([](const TVector<CAny>& InArgs)->CAny
        {
            float Value=**reinterpret_cast<const float**>(InArgs[0].GetPointer());
            return CString(U"Null");
        });
        Functions->VirtualFunctionTable.Add(ToStringFunction->ID);
    }
}

static  CNullObjectPtr * Type= new CNullObjectPtr();

CNullObjectPtr *CNullObjectPtr::GetType()
{
    return Type;
}